import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Vector;


public class Tiger 
{
	private CoverageMatrix A;
	private Collection<Component> P; //already under monitor
	private Collection<Test> O; //list of tests with outcomes
	private Collection<Component> C; //components 
	private List<Pair<Component, Double>> R;
	
	public Tiger(Collection<Component> C, CoverageMatrix A, Collection<Component> P, Collection<Test> O)
	{
		//this.C = C;
		this.C = new LinkedList<>(C);
		this.A = new CoverageMatrix(A.getArray(), A.getArray().length, A.getArray()[0].length);
		this.P = new LinkedList<>(P);
		this.O = new LinkedList<>(O);
	}
	
	/**
	 * runs tiger algorithm following the instructions from the article
	 */
	public void Run()
	{
		SFL sfl = new SFL(C, O, A);
		R = sfl.Run();
		
		List<Pair<Component, Double>> R_ = new LinkedList<Pair<Component,Double>>(R); 
		for(int i = 0; i < R.size(); i++) //R' = R / P
		{
			Pair<Component, Double> c = R.get(i);
			if(P.contains(c.first)) 
			{
				R_.remove(c);
			}
		}
		if(R_.isEmpty()) return;
		final Component c = R_.get(0).first;
		updateA(A, c);
		c.setIsMonitored(true);
		Test t = new Test(O.size()) 
		{
			protected boolean runTest(Vector<Component> componentsSet) 
			{
				return TestSimulation.RunTest(c);
			}
		};
		t.startTest(null);
		O.add(t);
		P.add(c);
	}
	
	/**
	 * updating A to include test with C as a monitored component
	 * @param A - coverage matrix
	 * @param c - component
	 */
	private static void updateA(CoverageMatrix A, Component c)
	{
		Vector<Integer> indexes = new Vector<Integer>();
		Component curr = c;
		while(curr != null)
		{
			indexes.add(curr.getId());
			curr = curr.getPredecessor();
		}
		int[] newRow = new int[A.getArray()[0].length];
		for (int i = 0; i < indexes.size(); i++) 
		{
			newRow[indexes.elementAt(i)] = 1;
		}
		A.addRow(newRow);
	}
	
	/**
	 * getters: 
	 */
	
	public CoverageMatrix getCoverageMatrix()
	{
		return A;
	}
	
	public Collection<Test> getTestOutcomes()
	{
		return O;
	}
	
	public Collection<Component> getMonitoredComponents()
	{
		return P;
	}
	
	public Collection<Component> getComponents()
	{
		return C;
	}
	
	public List<Pair<Component, Double>> getR()
	{
		return R;
	}
}
